home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 July: Mac OS SDK / Dev.CD Jul 97 SDK1.toast / Development Kits (Disc 1) / QuickDraw 3D / Samples / SampleCode / Picking Mesh ShapeParts / Sources / PickMeshShapePart.c next >
Encoding:
Text File  |  1996-05-21  |  12.0 KB  |  525 lines  |  [TEXT/CWIE]

  1. // PickMeshShapePart.c
  2. //
  3. // This demonstrates how to use picks  to test which parts of a mesh geometry have
  4. // been hit.  When the mesh is picked the fPickParts value set from the ShapeParts
  5. // menu controls the parts tested: object, face, edge, or vertex.  As the returned
  6. // hits  in the pick are processed the corresponding part of the mesh is draw in a
  7. // different color  and the name  of that part is displayed in the window's  upper
  8. // left corner.
  9. //
  10. // The vertex and edge tolerance levels  set in CreatePick() control how close the
  11. // window point pick must be to the given part.
  12. //
  13. // Robert Dierkes - November 11, 1995
  14. // 
  15. // ©1994-95 Apple computer Inc., All Rights Reserved
  16. //
  17.  
  18. // system headers
  19. #include <Windows.h>
  20.  
  21. // for QuickDraw 3D
  22. #include "QD3D.h"
  23. #include "QD3DMath.h"
  24. #include "QD3DDrawContext.h"
  25. #include "QD3DShader.h"
  26. #include "QD3DGroup.h"
  27. #include "QD3DPick.h"
  28.  
  29.  
  30. #include "PickMeshShapePart.h"
  31.  
  32.  
  33. //-------------------------------------------------------------------------------------------
  34. // function prototypes
  35.  
  36. void TickDelay(
  37.     long    time);
  38.  
  39. TQ3Status DoGroupPicking(
  40.     TQ3ViewObject        view,
  41.     TQ3GroupObject        group,
  42.     TQ3PickObject        pick);
  43.  
  44. void GetRandomRGBColor(
  45.     TQ3ColorRGB        *pColorRGB);
  46.  
  47. TQ3Status ChangeMeshFaceColor(
  48.     TQ3GeometryObject    meshGeo,
  49.     TQ3MeshFace            meshFace,
  50.     DocumentPtr            theDocument);
  51.  
  52. TQ3Status ChangeMeshEdgeColor(
  53.     TQ3GeometryObject    meshGeo,
  54.     TQ3MeshEdge            meshEdge,
  55.     DocumentPtr            theDocument);
  56.  
  57. TQ3Status ChangeMeshVertexColor(
  58.     TQ3GeometryObject    meshGeo,
  59.     TQ3MeshVertex        meshVertex,
  60.     DocumentPtr            theDocument);
  61.  
  62. TQ3Status HandleMeshPickHits(
  63.     TQ3PickObject        pick,
  64.     DocumentPtr            theDocument);
  65.  
  66. TQ3Status CreatePick(
  67.     TQ3PickObject        *pPick);
  68.  
  69.  
  70. //-------------------------------------------------------------------------------------------
  71. //
  72.  
  73. #define    kDelay            30
  74. #define    kTextLocationX    30
  75. #define    kTextLocationY    30
  76.  
  77. static TQ3PickObject    gPick = NULL;
  78.  
  79.  
  80.  
  81. //-------------------------------------------------------------------------------------------
  82.  
  83. TQ3Status InitPicking(
  84.     void)
  85. {
  86.     return CreatePick(&gPick);
  87. }
  88.  
  89.  
  90. TQ3Status ExitPicking(
  91.     void)
  92. {
  93.     if (gPick != NULL) {
  94.         Q3Object_Dispose(gPick);
  95.         gPick = NULL;
  96.     }
  97.  
  98.     return kQ3Success;
  99. }
  100.  
  101.  
  102. static
  103. void TickDelay(
  104.     long    time)
  105. {
  106.     long    ticks,
  107.             startTicks;
  108.  
  109.     startTicks = ticks = TickCount();
  110.  
  111.     while (ticks - startTicks != time ) {
  112.         ticks = TickCount();
  113.     }
  114. }
  115.  
  116.  
  117. static
  118. TQ3Status DoGroupPicking(
  119.     TQ3ViewObject        view,
  120.     TQ3GroupObject        group,
  121.     TQ3PickObject        pick)
  122. {
  123.     TQ3Status            status;
  124.     TQ3ViewStatus        viewStatus;
  125.  
  126.     if ((status = Q3View_StartPicking(view, pick)) == kQ3Failure)
  127.         return status;
  128.  
  129.     do {
  130.         status = Q3DisplayGroup_Submit(group, view);
  131.  
  132.         viewStatus = Q3View_EndPicking(view);
  133.     } while (viewStatus == kQ3ViewStatusRetraverse);
  134.  
  135.     if (viewStatus != kQ3ViewStatusDone) {
  136.         status = kQ3Failure;
  137.     }
  138.  
  139.     return status;
  140. }
  141.  
  142.  
  143. static
  144. void GetRandomRGBColor(
  145.     TQ3ColorRGB        *pColorRGB)
  146. {
  147.     unsigned long    ticks;
  148.  
  149.     ticks = TickCount();
  150.     Q3ColorRGB_Set(pColorRGB,
  151.         (ticks % 10)   / 10.0,
  152.         (ticks % 100)  / 100.0,
  153.         (ticks % 1000) / 1000.0);
  154. }
  155.  
  156.  
  157. static
  158. TQ3Status ChangeMeshFaceColor(
  159.     TQ3GeometryObject    meshGeo,
  160.     TQ3MeshFace            meshFace,
  161.     DocumentPtr            theDocument)
  162. {
  163.     TQ3Status        status;
  164.     TQ3AttributeSet    attributeSet;
  165.     TQ3ColorRGB        colorRGB;
  166.  
  167.     status = kQ3Failure;
  168.  
  169.     if (meshGeo  == NULL  ||
  170.         meshFace == NULL) {
  171.         return status;
  172.     }
  173.  
  174.     /* Get the face attributes */
  175.     if ((status = Q3Mesh_GetFaceAttributeSet(meshGeo, meshFace, &attributeSet)) == kQ3Failure) {
  176.         return status;
  177.     }
  178.  
  179.     /* Create an attributes if none */
  180.     if (attributeSet == NULL) {
  181.         if ((attributeSet = Q3AttributeSet_New()) == NULL) {
  182.             return kQ3Failure;
  183.         }
  184.     }
  185.  
  186.     GetRandomRGBColor(&colorRGB);
  187.     if ((status = Q3AttributeSet_Add(attributeSet, kQ3AttributeTypeDiffuseColor, &colorRGB)) == kQ3Success) {
  188.  
  189.         char    partTypeString[] = {"\pFace"};
  190.  
  191.         /* Set new face color */
  192.         status = Q3Mesh_SetFaceAttributeSet(meshGeo, meshFace, attributeSet);
  193.  
  194.         /* Redraw the mesh */
  195.         DrawDocumentData(theDocument);
  196.         MoveTo(kTextLocationX, kTextLocationY);
  197.         DrawText((void *) partTypeString, 1, (short) partTypeString[0]);
  198.         TickDelay(kDelay);
  199.  
  200.         /* Remove new face color */
  201.         status = Q3Mesh_SetFaceAttributeSet(meshGeo, meshFace, NULL);
  202.         DrawDocumentData(theDocument);
  203.     }
  204.  
  205.     Q3Object_Dispose(attributeSet);
  206.  
  207.     return status;
  208. }
  209.  
  210.  
  211. static
  212. TQ3Status ChangeMeshEdgeColor(
  213.     TQ3GeometryObject    meshGeo,
  214.     TQ3MeshEdge            meshEdge,
  215.     DocumentPtr            theDocument)
  216. {
  217.     TQ3Status        status;
  218.     TQ3AttributeSet    attributeSet1,
  219.                     attributeSet2;
  220.     TQ3MeshVertex    meshVertex1,
  221.                     meshVertex2;
  222.     TQ3ColorRGB        colorRGB;
  223.  
  224.     status = kQ3Failure;
  225.  
  226.     if (meshGeo  == NULL  ||
  227.         meshEdge == NULL) {
  228.         return status;
  229.     }
  230.  
  231.     attributeSet1 = NULL;
  232.     attributeSet2 = NULL;
  233.  
  234.     /*
  235.      * Set color on both vertices of this edge
  236.      *
  237.      * We change the vertex attributes instead of the edge attributes because we can only
  238.      * see the effects of an edge attribute when the fill style is kQ3FillStyleEdges.  We
  239.      * could use kQ3FillStyleEdges rather than the current fill of kQ3FillStyleFilled but
  240.      * then we couldn't see the attributes on the vertex and face. 
  241.      */
  242.     if ((status = Q3Mesh_GetEdgeVertices(meshGeo, meshEdge, &meshVertex1, &meshVertex2)) == kQ3Failure) {
  243.         return status;
  244.     }
  245.  
  246.     /* Get the vertex attributes */
  247.     if (((status = Q3Mesh_GetVertexAttributeSet(meshGeo, meshVertex1, &attributeSet1)) == kQ3Failure)  ||
  248.         ((status = Q3Mesh_GetVertexAttributeSet(meshGeo, meshVertex2, &attributeSet2)) == kQ3Failure)) {
  249.         goto ExitChangeMeshEdgeColor;
  250.     }
  251.  
  252.     /* Create an attributes if none */
  253.     if (attributeSet1 == NULL) {
  254.         if ((attributeSet1 = Q3AttributeSet_New()) == NULL) {
  255.             goto ExitChangeMeshEdgeColor;
  256.         }
  257.     }
  258.  
  259.     if (attributeSet2 == NULL) {
  260.         if ((attributeSet2 = Q3AttributeSet_New()) == NULL) {
  261.             goto ExitChangeMeshEdgeColor;
  262.         }
  263.     }
  264.  
  265.     GetRandomRGBColor(&colorRGB);
  266.     if (((status = Q3AttributeSet_Add(attributeSet1, kQ3AttributeTypeDiffuseColor, &colorRGB)) == kQ3Success)  &&
  267.         ((status = Q3AttributeSet_Add(attributeSet2, kQ3AttributeTypeDiffuseColor, &colorRGB)) == kQ3Success)) {
  268.  
  269.         char    partTypeString[] = {"\pEdge"};
  270.  
  271.         /* Set new vertex color */
  272.         if (((status = Q3Mesh_SetVertexAttributeSet(meshGeo, meshVertex1, attributeSet1)) == kQ3Success)  &&
  273.             ((status = Q3Mesh_SetVertexAttributeSet(meshGeo, meshVertex2, attributeSet2)) == kQ3Success)) {
  274.  
  275.             /* Redraw the mesh */
  276.             DrawDocumentData(theDocument);
  277.             MoveTo(kTextLocationX, kTextLocationY);
  278.             DrawText((void *) partTypeString, 1, (short) partTypeString[0]);
  279.             TickDelay(kDelay);
  280.         }
  281.  
  282.         /* Remove new vertex color */
  283.         status = Q3Mesh_SetVertexAttributeSet(meshGeo, meshVertex1, NULL);
  284.         status = Q3Mesh_SetVertexAttributeSet(meshGeo, meshVertex2, NULL);
  285.         DrawDocumentData(theDocument);
  286.     }
  287.  
  288. ExitChangeMeshEdgeColor:
  289.  
  290.     if (attributeSet1 != NULL)
  291.         Q3Object_Dispose(attributeSet1);
  292.  
  293.     if (attributeSet2 != NULL)
  294.         Q3Object_Dispose(attributeSet2);
  295.  
  296.     return status;
  297. }
  298.  
  299.  
  300. static
  301. TQ3Status ChangeMeshVertexColor(
  302.     TQ3GeometryObject    meshGeo,
  303.     TQ3MeshVertex        meshVertex,
  304.     DocumentPtr            theDocument)
  305. {
  306.     TQ3Status        status;
  307.     TQ3AttributeSet    attributeSet;
  308.     TQ3ColorRGB        colorRGB;
  309.  
  310.     status = kQ3Failure;
  311.  
  312.     if (meshGeo    == NULL  ||
  313.         meshVertex == NULL) {
  314.         return status;
  315.     }
  316.  
  317.     /* Get the vertex attributes */
  318.     if ((status = Q3Mesh_GetVertexAttributeSet(meshGeo, meshVertex, &attributeSet)) == kQ3Failure) {
  319.         return status;
  320.     }
  321.  
  322.     /* Create an attributes if none */
  323.     if (attributeSet == NULL) {
  324.         if ((attributeSet = Q3AttributeSet_New()) == NULL) {
  325.             return kQ3Failure;
  326.         }
  327.     }
  328.  
  329.     GetRandomRGBColor(&colorRGB);
  330.     if ((status = Q3AttributeSet_Add(attributeSet, kQ3AttributeTypeDiffuseColor, &colorRGB)) == kQ3Success) {
  331.  
  332.         char    partTypeString[] = {"\pVertex"};
  333.  
  334.         /* Set new vertex color */
  335.         status = Q3Mesh_SetVertexAttributeSet(meshGeo, meshVertex, attributeSet);
  336.  
  337.         /* Redraw the mesh */
  338.         DrawDocumentData(theDocument);
  339.         MoveTo(kTextLocationX, kTextLocationY);
  340.         DrawText((void *) partTypeString, 1, (short) partTypeString[0]);
  341.         TickDelay(kDelay);
  342.  
  343.         /* Remove new vertex color */
  344.         status = Q3Mesh_SetVertexAttributeSet(meshGeo, meshVertex, NULL);
  345.         DrawDocumentData(theDocument);
  346.     }
  347.  
  348.     Q3Object_Dispose(attributeSet);
  349.  
  350.     return status;
  351. }
  352.  
  353.  
  354. static
  355. TQ3Status HandleMeshPickHits(
  356.     TQ3PickObject        pick,
  357.     DocumentPtr            theDocument)
  358. {
  359.     TQ3HitData            hitData;
  360.     TQ3ObjectType        objectType;
  361.     unsigned long        hitIndex,
  362.                         numHits;
  363.     TQ3Status            status;
  364.  
  365.     status  = kQ3Failure;
  366.     numHits = 0;
  367.  
  368.     if (pick == NULL)
  369.         goto ExitHandleMeshPickHits;
  370.  
  371.     if ((status = Q3Pick_GetNumHits(pick, &numHits)) == kQ3Failure)
  372.         goto ExitHandleMeshPickHits;
  373.  
  374.     /* Get each hit */
  375.     for (hitIndex = 0; hitIndex < numHits; hitIndex++) {
  376.  
  377.         if (Q3Pick_GetHitData(pick, hitIndex, &hitData) == kQ3Failure) {
  378.             DebugStr("\pHandleMeshPickHits: Q3Pick_GetHitData failed");
  379.             goto ExitHandleMeshPickHits;
  380.         }
  381.  
  382.         /* Test if hit data contains an object and shape part */
  383.         if (! HitData_Has_Object(hitData)) {
  384.             DebugStr("\pHandleMeshPickHits: no object information returned in Q3Pick_GetHitData");
  385.             goto ExitHandleMeshPickHits;
  386.         }
  387.  
  388.         if (! HitData_Has_ShapePart(hitData)) {
  389.             DebugStr("\pHandleMeshPickHits: no shape part information returned in Q3Pick_GetHitData");
  390.             goto ExitHandleMeshPickHits;
  391.         }
  392.  
  393.         /* Was the shapePart a mesh part? */
  394.         if (Q3ShapePart_GetType (hitData.shapePart) == kQ3ShapePartTypeMeshPart) {
  395.             TQ3GeometryObject    meshGeo;
  396.  
  397.             /* hitData.object was tested for NULL by HitData_Has_Object() above */
  398.             meshGeo = hitData.object;
  399.  
  400.             /* Or use this to get the shape part hit: objectType = Q3Object_GetLeafType(hitData.shapePart); */
  401.             objectType = Q3MeshPart_GetType(hitData.shapePart);
  402.  
  403.             switch (objectType) {
  404.                 case kQ3MeshPartTypeMeshFacePart:
  405.                     {
  406.                         TQ3MeshFace        meshFace;
  407.  
  408.                         if (Q3MeshFacePart_GetFace(hitData.shapePart, &meshFace) == kQ3Failure) {
  409.                             goto ExitHandleMeshPickHits;
  410.                         }
  411.  
  412.                         status = ChangeMeshFaceColor(meshGeo, meshFace, theDocument);
  413.                     }
  414.                     break;
  415.  
  416.                 case kQ3MeshPartTypeMeshEdgePart:
  417.                     {
  418.                         TQ3MeshEdge        meshEdge;
  419.  
  420.                         if (Q3MeshEdgePart_GetEdge(hitData.shapePart, &meshEdge) == kQ3Failure) {
  421.                             goto ExitHandleMeshPickHits;
  422.                         }
  423.  
  424.                         status = ChangeMeshEdgeColor(meshGeo, meshEdge, theDocument);
  425.                     }
  426.                     break;
  427.  
  428.                 case kQ3MeshPartTypeMeshVertexPart:
  429.                     {
  430.                         TQ3MeshVertex    meshVertex;
  431.  
  432.                         if (Q3MeshVertexPart_GetVertex(hitData.shapePart, &meshVertex) == kQ3Failure) {
  433.                             goto ExitHandleMeshPickHits;
  434.                         }
  435.  
  436.                         status = ChangeMeshVertexColor(meshGeo, meshVertex, theDocument);
  437.                     }
  438.                     break;
  439.  
  440.                 default:
  441.                     break;
  442.             }
  443.         }
  444.  
  445.         Q3Hit_EmptyData(&hitData);
  446.     }
  447.  
  448. ExitHandleMeshPickHits:
  449.  
  450.     if (numHits > 0) {
  451.         Q3Hit_EmptyData(&hitData);
  452.     }
  453.  
  454.     if ((status = Q3Pick_EmptyHitList(pick)) == kQ3Failure)
  455.         DebugStr("\pHandleMeshPickHits: Q3Pick_EmptyHitList failed");
  456.  
  457.     return status;
  458. }
  459.  
  460.  
  461. static
  462. TQ3Status CreatePick(
  463.     TQ3PickObject        *pPick)
  464. {
  465.     TQ3WindowPointPickData    data;
  466.     TQ3Status                status;
  467.  
  468.     status = kQ3Failure;
  469.  
  470.     if (pPick  == NULL)
  471.         return status;
  472.  
  473.     /* Create pick object */
  474.     data.data.sort = kQ3PickSortNearToFar;
  475.     data.data.mask = kQ3PickDetailMaskObject  |    /* Request only object and shape parts */
  476.                      kQ3PickDetailMaskShapePart;
  477.     data.data.numHitsToReturn = kQ3ReturnAllHits;
  478.     
  479.     Q3Point2D_Set(&data.point, 0.0, 0.0);
  480.     data.vertexTolerance = 5.0;                    /* Set vertex and edge tolerences */
  481.     data.edgeTolerance   = 3.0;
  482.  
  483.     if ((*pPick = Q3WindowPointPick_New(&data)) != NULL)
  484.         status = kQ3Success;
  485.  
  486.     return status;
  487. }
  488.  
  489.  
  490. TQ3Status DoPicking(
  491.     Point                *pWhere,    /* local window coordinates */
  492.     DocumentPtr            theDocument)
  493. {
  494.     TQ3Status            status;
  495.     TQ3Point2D            point;
  496.  
  497.     status = kQ3Failure;
  498.  
  499.     if (theDocument->fView  == NULL  ||
  500.         theDocument->fModel == NULL  ||
  501.         theDocument->fPickPartStyle == NULL  ||
  502.         gPick == NULL) {
  503.  
  504.         goto DoPickingExit;
  505.     }
  506.  
  507.     /* Set pick part style with parts selected in the menu */
  508.     if ((status = Q3PickPartsStyle_Set(theDocument->fPickPartStyle, theDocument->fPickParts)) == kQ3Failure)
  509.         goto DoPickingExit;
  510.  
  511.     /* Set the pick's point to mouse location */
  512.     Q3Point2D_Set(&point, pWhere->h, pWhere->v);
  513.     if ((status = Q3WindowPointPick_SetPoint(gPick, &point)) == kQ3Failure)
  514.         goto DoPickingExit;
  515.  
  516.     if ((status = DoGroupPicking(theDocument->fView, theDocument->fModel, gPick)) == kQ3Failure)
  517.         goto DoPickingExit;
  518.  
  519.     /* Handle hit(s) on mesh */
  520.     status = HandleMeshPickHits(gPick, theDocument);
  521.  
  522. DoPickingExit:
  523.     return status;
  524. }
  525.